package com.raojunxue.company.interceptor;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

import com.google.appengine.repackaged.org.apache.commons.logging.Log;
import com.google.appengine.repackaged.org.apache.commons.logging.LogFactory;
import com.raojunxue.company.annotation.Before;
import com.raojunxue.company.util.AnnotationUtil;
import com.raojunxue.company.util.StringUtil;

/**
 * Executer for {@link Before} annotation
 * @author Xie Dongming
 *
 */
public class BeforeExecuter {

	private static Log log = LogFactory.getLog(BeforeExecuter.class);
	
	/**
	 * 
	 * execute before action for target method on target object. if there is no before action for the 
	 * target method, this executer will do nothing and just return. Note this executer will not invoke
	 * the target method but just invoke before action.
	 * 
	 * @param targetObject
	 * @param targetMethod
	 */
	public void execute(Object targetObject, Method targetMethod) {
		List<Method> beforeMtds = AnnotationUtil.getAnnotatedMethods(targetObject.getClass(), Before.class);
		for (Method currentBefore : beforeMtds) {
			if (isBeforeNeededForMethod(currentBefore, targetMethod.getName())) {
					try {
						currentBefore.setAccessible(true);
						currentBefore.invoke(targetObject, (Object[]) null);
					} catch (IllegalArgumentException e) {
						log.debug(e.getMessage());
					} catch (IllegalAccessException e) {
						log.debug(e.getMessage());
					} catch (InvocationTargetException e) {
						log.debug(e.getMessage());
					}
				
			}
		}
	}

	private boolean isBeforeNeededForMethod(Method currentBefore, String method) {
		Before before = currentBefore.getAnnotation(Before.class);
		return StringUtil.contains(before.include(), method);
	}

}
